package ext.acae2.dms.parse;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import wt.log4j.LogR;
import ext.acae2.dms.bean.DocumentBean;
import ext.acae2.dms.bean.EPMDocumentBean;
import ext.acae2.dms.bean.PartBean;
import ext.acae2.util.MappingUtil;
import ext.acae2.util.ParameterUtil;
import ext.acae2.util.StringUtil;

public class ParsePartAndDoc {

	private static final Logger LOGGER = LogR.getLogger(ParsePartAndDoc.class
			.getName());

	@SuppressWarnings("rawtypes")
	public static Map<String, List> execute(Document doc, XPath xpath,
			String rootFolderPath, String supplier)
			throws XPathExpressionException {

		// create partList,docList,epmDocList
		List<PartBean> partList = new ArrayList<PartBean>();
		List<DocumentBean> docList = new ArrayList<DocumentBean>();
		List<EPMDocumentBean> epmDocList = new ArrayList<EPMDocumentBean>();

		LOGGER.debug("<<< Start parsePartAndDoc");

		// use XPath validate XPath Expression
		XPathExpression pathExpression = xpath
				.compile("//PLMXML/ProductView/Occurrence/@instancedRef");
		// have result
		Object result = pathExpression.evaluate(doc, XPathConstants.NODESET);

		// node-set to NodeList
		// result to DOM NodeList
		NodeList nodes = (NodeList) result;

		// PartBean amount
		for (int i = 0; i < nodes.getLength(); i++) {

			LOGGER.debug("Part amount: " + nodes.getLength());
			PartBean partBean = new PartBean();

			// PartBean Id --(occurrenceId)
			// --//PLMXML/ProductView/Occurrence/@id
			pathExpression = xpath
					.compile("//PLMXML/ProductView/Occurrence/@id");
			NodeList partBeanIdNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			String partBeanId = partBeanIdNodes.item(i).getNodeValue();
			partBean.setId(partBeanId);
			LOGGER.debug("	!!!	PartBean Id: "
					+ partBeanId
					+ " --(occurrenceId)	!!! --//PLMXML/ProductView/Occurrence/@id");

			// PartBean ParentId --(parentRefId)
			// --//PLMXML/ProductView/Occurrence/@parentRef
			pathExpression = xpath
					.compile("//PLMXML/ProductView/Occurrence[@id = '"
							+ partBeanId + "']/@parentRef");
			NodeList parentIdNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			if (parentIdNodes.item(0) != null) {
				String parentId = parentIdNodes.item(0).getNodeValue()
						.substring(1);
				partBean.setParentId(parentId);
				LOGGER.debug("	!!!	PartBean ParentId: "
						+ parentId
						+ " --(parentRefId)	!!! --//PLMXML/ProductView/Occurrence/@parentRef");
			}

			// productRevisionId
			String productRevisionId = nodes.item(i).getNodeValue()
					.substring(1);
			LOGGER.debug("productRevisionId: " + productRevisionId);

			// Part Revision --(productRevision)
			// --//PLMXML/ProductRevision/@revision
			pathExpression = xpath.compile("//PLMXML/ProductRevision[@id='"
					+ productRevisionId + "']/@revision");
			NodeList partRevisionNodes = (NodeList) pathExpression.evaluate(
					doc, XPathConstants.NODESET);
			String partRevision = partRevisionNodes.item(0).getNodeValue();
			partBean.setVersion(partRevision.substring(partRevision.length() - 1));
			LOGGER.debug("	!!! Part Revision: "
					+ partRevision
					+ " --(productRevision) !!! --//PLMXML/ProductRevision/@revision");

			// productId --//PLMXML/ProductRevision/@masterRef
			pathExpression = xpath.compile("//PLMXML/ProductRevision[@id='"
					+ productRevisionId + "']/@masterRef");
			NodeList productIdNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			String productId = productIdNodes.item(0).getNodeValue()
					.substring(1);
			LOGGER.debug("productId: " + productId
					+ " --//PLMXML/ProductRevision/@masterRef");

			// PartBean Name --(productName) --//PLMXML/Product/@name
			pathExpression = xpath.compile("//PLMXML/Product[@id='" + productId
					+ "']/@name");
			NodeList partNameNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			String partName = partNameNodes.item(0).getNodeValue();
			
			if(partName.contains("_")){
				int endIndex = partName.lastIndexOf("_");
				partName.substring(0,endIndex);
			}else{
				partBean.setName(partName);
			}
			
			LOGGER.debug("	!!! PartBean Name: " + partName
					+ " --(productName) !!! --//PLMXML/Product/@name");

			// PartBean Type --(productSubType) --//PLMXML/Product/@subType
			pathExpression = xpath.compile("//PLMXML/Product[@id='" + productId
					+ "']/@subType");
			NodeList partTypeNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			String partType = partTypeNodes.item(0).getNodeValue();
			partBean.setType(partType);
			LOGGER.debug("	!!! PartBean Type: " + partType
					+ " --(productSubType) !!! --//PLMXML/Product/@subType");

			// PartBean Number --(productProductId)
			// --//PLMXML/Product/@productId
			pathExpression = xpath.compile("//PLMXML/Product[@id='" + productId
					+ "']/@productId");
			NodeList partNumberNodes = (NodeList) pathExpression.evaluate(doc,
					XPathConstants.NODESET);
			String partNumber = partNumberNodes.item(0).getNodeValue();
			partBean.setNumber(partNumber);
			partBean.setTCNo(partNumber);
			LOGGER.debug("	!!! PartBean Number: " + partNumber
					+ " --(productProductId) !!! --//PLMXML/Product/@productId");

			// associatedAttachmentRefs
			// --//PLMXML/ProductView/Occurrence/@associatedAttachmentRefs
			pathExpression = xpath
					.compile("//PLMXML/ProductView/Occurrence[@instancedRef='#"
							+ productRevisionId
							+ "']/@associatedAttachmentRefs");
			NodeList associatedAttachmentRefsNodes = (NodeList) pathExpression
					.evaluate(doc, XPathConstants.NODESET);
			String associatedAttachmentRefs = associatedAttachmentRefsNodes
					.item(0).getNodeValue();
			LOGGER.debug("associatedAttachmentRefs: "
					+ associatedAttachmentRefs
					+ " --//PLMXML/ProductView/Occurrence/@associatedAttachmentRefs");

			String[] attachmentRefs = associatedAttachmentRefs.split("#");
			for (int j = 1; j < attachmentRefs.length; j++) {

				// attachmentRef
				// --//PLMXML/ProductView/AssociatedAttachment/@attachmentRef
				pathExpression = xpath
						.compile("//PLMXML/ProductView/AssociatedAttachment[@id='"
								+ attachmentRefs[j].trim()
								+ "']/@attachmentRef");
				NodeList attachmentRefNodes = (NodeList) pathExpression
						.evaluate(doc, XPathConstants.NODESET);
				String attachmentRef = attachmentRefNodes.item(0)
						.getNodeValue().substring(1);
				LOGGER.debug("attachmentRef: "
						+ attachmentRef
						+ " --//PLMXML/ProductView/AssociatedAttachment/@attachmentRef");

				// role --//PLMXML/ProductView/AssociatedAttachment/@role
				pathExpression = xpath
						.compile("//PLMXML/ProductView/AssociatedAttachment[@attachmentRef='#"
								+ attachmentRef + "']/@role");
				NodeList roleNodes = (NodeList) pathExpression.evaluate(doc,
						XPathConstants.NODESET);
				String role = roleNodes.item(0).getNodeValue();
				LOGGER.debug("role: " + role
						+ " --//PLMXML/ProductView/AssociatedAttachment/@role");

				// file or attribute
				if (!role.equalsIgnoreCase(ParameterUtil.IMAN_MASTER_FORM)) {

					// externalFiles --//PLMXML/DataSet/@memberRefs
					pathExpression = xpath.compile("//PLMXML/DataSet[@id='"
							+ attachmentRef + "']/@memberRefs");
					NodeList memberRefsNodes = (NodeList) pathExpression
							.evaluate(doc, XPathConstants.NODESET);
					
					if (memberRefsNodes.item(0) != null) {
						
						pathExpression = xpath.compile("//PLMXML/DataSet[@id='"
								+ attachmentRef + "']/@type");
						NodeList typeNodes = (NodeList) pathExpression
								.evaluate(doc, XPathConstants.NODESET);
						String type = typeNodes.item(0).getNodeValue();
						
						String memberRefs = memberRefsNodes.item(0)
								.getNodeValue();
						LOGGER.debug("memberRefs: " + memberRefs
								+ " --//PLMXML/DataSet/@memberRefs");
						String[] externalFiles = memberRefs.split("#");

						// format --//PLMXML/ExternalFile/@format
						for (int k = 1; k < externalFiles.length; k++) {
							pathExpression = xpath
									.compile("//PLMXML/ExternalFile[@id='"
											+ externalFiles[k].trim()
											+ "']/@format");
							NodeList formatNodes = (NodeList) pathExpression
									.evaluate(doc, XPathConstants.NODESET);
							String format = formatNodes.item(0).getNodeValue();
							LOGGER.debug("format: " + format
									+ " --//PLMXML/ExternalFile/@format");
							String newFormat = format.toUpperCase();

							// create DocumentBean or EPMDocumentBean
							if (ParameterUtil.EPMDOCUMENT_TYPE
									.contains(newFormat)) {
								EPMDocumentBean epmDocumentBean = new EPMDocumentBean();

								// locationRef
								// --//PLMXML/ExternalFile/@locationRef
								pathExpression = xpath
										.compile("//PLMXML/ExternalFile[@id='"
												+ externalFiles[k].trim()
												+ "']/@locationRef");
								NodeList locationRefNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);
								String locationRef = locationRefNodes.item(0)
										.getNodeValue();
								locationRef = locationRef
										.replaceAll("%20", " ");
								locationRef = locationRef.replaceAll("\\\\", File.separator);
								
								LOGGER.debug("locationRef: "
										+ locationRef
										+ " --//PLMXML/ExternalFile/@locationRef");

								epmDocumentBean.setId(externalFiles[k].trim());
								epmDocumentBean.setLocationRef(rootFolderPath
										+ locationRef);
								epmDocumentBean.setType(type);
								epmDocumentBean.setFormat(format);
								epmDocumentBean.setPartId(partBeanId);
								LOGGER.debug("	!!! epmDocumentBean Id: "
										+ externalFiles[k].trim() + " !!!");
								LOGGER.debug("	!!! epmDocumentBean LocationRef: "
										+ locationRef + " !!!");
								LOGGER.debug("	!!! epmDocumentBean Type: "
										+ type + " !!!");
								LOGGER.debug("	!!! epmDocumentBean format: "
										+ format + " !!!");
								LOGGER.debug("	!!! epmDocumentBean PartId: "
										+ partBeanId + " !!!");

								pathExpression = xpath
										.compile("//PLMXML/DataSet/@memberRefs");
								NodeList dataSetMemberRefsNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);
								for (int l = 0; l < dataSetMemberRefsNodes
										.getLength(); l++) {

									String dataSetMemberRefs = dataSetMemberRefsNodes
											.item(l).getNodeValue();

									if (dataSetMemberRefs
											.contains(externalFiles[k].trim())) {
										pathExpression = xpath
												.compile("//PLMXML/DataSet[@memberRefs='"
														+ dataSetMemberRefs
														+ "']/@version");
										NodeList versionNodes = (NodeList) pathExpression
												.evaluate(doc,
														XPathConstants.NODESET);
										String version = versionNodes.item(0)
												.getNodeValue();

										epmDocumentBean.setVersion(version);
										LOGGER.debug("	!!! epmDocumentBean Version: "
												+ version
												+ " --//PLMXML/DataSet/@version");
									}
								}

								int startIndex = locationRef.lastIndexOf(File.separator);
//								if(locationRef.contains("_")){
//									int endIndex = locationRef.lastIndexOf("_");
//									epmDocumentBean.setName(locationRef.substring(
//											startIndex + 1,endIndex));
//								}else{
									int endIndex = locationRef.lastIndexOf(".");
									epmDocumentBean.setNumber(locationRef.substring(
											startIndex + 1,endIndex));
//								}
								epmDocumentBean.setName(epmDocumentBean
										.getNumber()+"."+epmDocumentBean.getFormat());
								epmDocumentBean.setState(ParameterUtil.STATE);

								LOGGER.debug("	!!! epmDocumentBean State: "
										+ ParameterUtil.STATE + " !!!");
								epmDocumentBean.setSupplier(supplier);
								LOGGER.debug("	!!! epmDocumentBean Supplier: "
										+ supplier + " !!!");
								epmDocList.add(epmDocumentBean);

							} else if (ParameterUtil.DOCUMENT_TYPE
									.contains(newFormat)) {
								DocumentBean documentBean = new DocumentBean();

								// locationRef
								// --//PLMXML/ExternalFile/@locationRef
								pathExpression = xpath
										.compile("//PLMXML/ExternalFile[@id='"
												+ externalFiles[k].trim()
												+ "']/@locationRef");
								NodeList locationRefNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);
								String locationRef = locationRefNodes.item(0)
										.getNodeValue();
								locationRef = locationRef
										.replaceAll("%20", " ");
								locationRef = locationRef.replaceAll("\\\\", File.separator);

								LOGGER.debug("locationRef: "
										+ locationRef
										+ " --//PLMXML/ExternalFile/@locationRef");

								documentBean.setId(externalFiles[k].trim());
								documentBean.setLocationRef(rootFolderPath
										+ locationRef);
								documentBean.setType(type);
								documentBean.setFormat(format);
								documentBean.setPartId(partBeanId);
								LOGGER.debug("	!!! documentBean Id: "
										+ externalFiles[k].trim() + " !!!");
								LOGGER.debug("	!!! documentBean LocationRef: "
										+ locationRef + " !!!");
								LOGGER.debug("	!!! documentBean Type: "
										+ type + " !!!");
								LOGGER.debug("	!!! documentBean format: "
										+ format + " !!!");
								LOGGER.debug("	!!! documentBean PartId: "
										+ partBeanId + " !!!");

								// name --//PLMXML/DataSet/@name
								pathExpression = xpath
										.compile("//PLMXML/DataSet[@memberRefs='#"
												+ externalFiles[k].trim()
												+ "']/@name");
								NodeList nameNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);
								String name = nameNodes.item(0).getNodeValue();
								LOGGER.debug("name: " + name
										+ " --//PLMXML/DataSet/@name");

								// version --//PLMXML/DataSet/@version
								pathExpression = xpath
										.compile("//PLMXML/DataSet[@name='"
												+ name + "']/@version");
								NodeList versionNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);
								String version = versionNodes.item(0)
										.getNodeValue();
								documentBean.setVersion(version);
								LOGGER.debug("	!!! documentBean Version: "
										+ version
										+ " --//PLMXML/DataSet/@version");

								int startIndex = locationRef.lastIndexOf(File.separator);
//								if(locationRef.contains("_")){
//									int endIndex = locationRef.lastIndexOf("_");
//									documentBean.setNumber(locationRef.substring(
//											startIndex + 1,endIndex));
//								}else{
									int endIndex = locationRef.lastIndexOf(".");
									documentBean.setNumber(locationRef.substring(
											startIndex + 1,endIndex));
//								}
								documentBean.setName(documentBean.getNumber()+"."+documentBean.getFormat());
								documentBean.setState(ParameterUtil.STATE);
								LOGGER.debug("	!!! documentBean State: "
										+ ParameterUtil.STATE + " !!!");
								documentBean.setSupplier(supplier);
								LOGGER.debug("	!!! epmDocumentBean Supplier: "
										+ supplier + " !!!");

								documentBean.setTITLE(documentBean.getName()
										+ "." + documentBean.getType());
								documentBean.setDOCUMENTID(documentBean
										.getNumber());
								documentBean.setOBJNAME(documentBean.getName());
								documentBean.setDOCUMENTTYPE(documentBean
										.getType());

								// externalFiles title and value
								pathExpression = xpath
										.compile("//PLMXML/Form[@id='"
												+ attachmentRef
												+ "']/UserData/UserValue/@title");
								NodeList TitleNodes = (NodeList) pathExpression
										.evaluate(doc, XPathConstants.NODESET);

									pathExpression = xpath
											.compile("//PLMXML/Form[@id='"
													+ attachmentRef
													+ "']/UserData/UserValue/@value");
									NodeList ValueNodes = (NodeList) pathExpression
											.evaluate(doc,
													XPathConstants.NODESET);

									// input attributes in PartBean map
									Map<String, String> map = new HashMap<String, String>();
									for (int l = 0; l < TitleNodes.getLength(); l++) {
										String title = TitleNodes.item(l)
												.getNodeValue();
										String value = ValueNodes.item(l)
												.getNodeValue();

										LOGGER.debug("@@@@@@" + title + "="
												+ value + "@@@@@@");

										title = title.toUpperCase();

//										if(title
//												.equalsIgnoreCase(MappingUtil.DRAWINGNO)){
//											documentBean.setNumber(value);
//										}
										
										if (title
												.equalsIgnoreCase(MappingUtil.MODEL)) {
											documentBean.setMODEL(value);
										} else if (title
												.equalsIgnoreCase(MappingUtil.DESIGN)) {
											documentBean.setDESIGN(value);
										} else if(title
												.equalsIgnoreCase(MappingUtil.COPYRIGHT)){
											documentBean.setCOPYRIGHT(value);
										}else {
											if (!value.isEmpty()) {
												map.put(title, value);
												documentBean
														.setREMARK(StringUtil
																.MapToString(map));
												LOGGER.debug("######"
														+ partBean.getREMARK()
														+ "######");
											}
										}
										documentBean.setMap(map);
									}
								docList.add(documentBean);
							}
						}
					}
				}
				if(role.equalsIgnoreCase(ParameterUtil.IMAN_MASTER_FORM)){
					// externalFiles title and value
					pathExpression = xpath.compile("//PLMXML/Form[@id='"
							+ attachmentRef + "']/UserData/UserValue/@title");
					NodeList TitleNodes = (NodeList) pathExpression.evaluate(
							doc, XPathConstants.NODESET);
					if(TitleNodes.getLength() != 0){
					pathExpression = xpath.compile("//PLMXML/Form[@id='"
							+ attachmentRef + "']/UserData/UserValue/@value");
					NodeList ValueNodes = (NodeList) pathExpression.evaluate(
							doc, XPathConstants.NODESET);

					// input attributes in PartBean map
					Map<String, String> map = new HashMap<String, String>();
					for (int l = 0; l < TitleNodes.getLength(); l++) {
						String title = TitleNodes.item(l).getNodeValue();
						String value = ValueNodes.item(l).getNodeValue();

						LOGGER.debug("@@@@@@" + title + "=" + value + "@@@@@@");

						title = title.toUpperCase();
						
						if (title.equalsIgnoreCase(MappingUtil.OBJNAME)) {
							partBean.setOBJNAME(value);
						} else if (title
								.equalsIgnoreCase(MappingUtil.DRAWINGNO)) {
							partBean.setDRAWINGNO(value);
							partBean.setNumber(value);
						} else if (title
								.equalsIgnoreCase(MappingUtil.CHARACTERTYPE)) {
							partBean.setCHARACTERTYPE(value);
						} else if (title.equalsIgnoreCase(MappingUtil.MASS)) {
							partBean.setMASS(value);
						} else if (title.equalsIgnoreCase(MappingUtil.UNITE)) {
							partBean.setUNITE(value);
						} else if (title.equalsIgnoreCase(MappingUtil.MODEL)) {
							partBean.setMODEL(value);
						} else if (title.equalsIgnoreCase(MappingUtil.DESIGN)) {
							partBean.setDESIGN(value);
						} else if (title.equalsIgnoreCase(MappingUtil.PARTTYPE)) {
							partBean.setPARTTYPE(value);
						} else if (title
								.equalsIgnoreCase(MappingUtil.BLANKSPEC)) {
							partBean.setBLANKSPEC(value);
						} else if (title
								.equalsIgnoreCase(MappingUtil.BLANKSTATE)) {
							partBean.setBLANKSTATE(value);
						} else if (title.equalsIgnoreCase(MappingUtil.MATERIAL)) {
							partBean.setMATERIAL(value);
						} else if (title
								.equalsIgnoreCase(MappingUtil.MATERIALSTANDARD)) {
							partBean.setMATERIALSTANDARD(value);
						} else if(title
								.equalsIgnoreCase(MappingUtil.COPYRIGHT)){
							partBean.setCOPYRIGHT(value);
						} else if(title
								.equalsIgnoreCase(MappingUtil.SECRETLEVEL)){
							partBean.setSECRETLEVEL(value);
						} else if(title
								.equalsIgnoreCase(MappingUtil.SECURITYDEADLINE)){
							partBean.setSECURITYDEADLINE(value);
						} else {
							if(!value.isEmpty()){
								map.put(title, value);
								partBean.setREMARK(StringUtil.MapToString(map));
								LOGGER.debug("######" + partBean.getREMARK()
										+ "######");
							}
						}
						partBean.setMap(map);
						partBean.setState(ParameterUtil.STATE);
					}}
					partList.add(partBean);
				}
			}
		}

		for (int i = 0; i < docList.size(); i++) {
			for (int j = 0; j < partList.size(); j++) {
				if (docList.get(i).getPartId().equals(partList.get(j).getId())) {
					if(partList.get(j).getParentId() != null){
						if (!partList.get(j).getParentId().isEmpty()) {
							docList.get(i).setPartId(partList.get(j).getParentId());
							partList.remove(partList.get(j));
						}
					}
				}
			}
		}
		
		// add partList,epmDocList,docList to map
		Map<String, List> map = new HashMap<String, List>();
		map.put(ParameterUtil.PARTBEAN, partList);
		map.put(ParameterUtil.EPMDOCUMENTBEAN, epmDocList);
		map.put(ParameterUtil.DOCUMENTBEAN, docList);

		LOGGER.debug(">>> End parsePartAndDoc");
		return map;
	}
}
